home *** CD-ROM | disk | FTP | other *** search
- /****************************************************************
- * KAFS.C
- *
- * Keyed Access File Definitions
- *
- * Keyed Access File System Version 2.0
- *
- * 2.0 Revised to contain keys and data in a single file.
- * Key Access Files (KAF) are self contained.
- * 9/23/92 - Added 'filecommit' function in KAFS.
- * 2.1 11/11/92 - Qualified rec value for delete, read_rec, write_rec
- *
- ****************************************************************/
- #include <dos.h>
- #include <fcntl.h>
- #include <stdio.h>
- #include <math.h>
- #include <sys\stat.h>
-
-
- /**********************************************************
- * Key Access files definitions
- **********************************************************/
-
- #define TRUE 1
- #define FALSE 0
-
- #define OK 0
- #define SOF -1 /* Start of File */
- #define FCLOSED -1
- #define ERR -1
- #define NOTFOUND -2
- #define FILEFULL -3
- #define KAEOF -4 /* Reached End Of File on Sequential Read */
-
- /**
- ** KEY ACCESS ERROR CODES - Value held in kaerror global Variable
- **
- 1 - File Already Open
- 2 - Not a valid KAFSII file
- 3 - Error Attempting to Open Data File
- 4 - File Not Open
- 5 - Seek Error on Data File
- 6 - Read Error on Data File
- 7 - Write Error on Data File
- 8 - Error Reading Hash Index Block
- 9 - Error Writing Hash Index Block
- 10 - Invalid Channel Number
- 11 - Passed Key Argument exceeds keysize
- 12 - File Name too Long or Invalid
- 13 - Rec exceeds file's extent
- **
- **/
-
-
-
- #define HBLOCKSIZE 1024
- #define KEYSTART 128 /* Start of File's Key Blocks */
- #define KEYFILES 16 /* Number of key files allowed */
- #define MAXRECSIZE 512 /* Maximum Record Size allowed */
- #define MAXKEYSIZE 40 /* Maximum Key Size allowed */
-
- /* ------------- File Definition Structure (Allow 256 Bytes) --------- */
- struct fildef {
- char signature[7]; /* KAFSII */
- char filename[16]; /* User's File Name */
- int keysize; /* Size of Key Field */
- int recsize; /* Size of a Record */
- long records; /* Number of Records */
- int kpb; /* Keys per Block */
- long hblocks; /* Hash blocks (calculated) */
- long dbeg; /* File Position for Data Beginning */
- };
-
- /* ------------- File Table Definition ---------------- */
- struct ft {
- int handle; /* Data File's handle */
- int keysize; /* Size of the key field */
- int recsize; /* Size of record */
- char fname[16];/* Filename (User's) */
- long records; /* File defined max records */
- long hblocks; /* Hash blocks (calculated) */
- int kpb; /* Keys per block (calculated) */
- long dbeg; /* File position for beginning of Data */
- };
-
-
- /*********************************************************************
- * Function Prototypes
- *********************************************************************/
-
- int ka_open(int, char *);
- void ka_close_all(void);
- void ka_close(int);
- int read_key(int, char *, void *);
- int read_rec(int, void *);
- int read_xrec(int, void *);
- int write_key(int, char *, void *);
- int write_rec(int, void *);
- int write_upd(int, void *);
- int rdelete(int, long);
- int read_seq(int, void *);
- int read_hblk(int, long);
- int write_hblk(int, long);
- long khash(char *, long);
-
- void filecommit(int);
-
- char hbuf[HBLOCKSIZE]; /* Define the Hash Buffer */
- long rec; /* Global Record Number */
- int kaerror = 0; /* Global Error Code */
- char *kaversion = "V2.01 - 11/11/92"; /* Version 2.0 */
- char key[MAXKEYSIZE+1]; /* Global Key 40 chars max */
-
- /* Define the file table structure */
- struct ft ftbl[KEYFILES+1]=
- {-1,0,0,"",0,0,0,0,
- -1,0,0,"",0,0,0,0,
- -1,0,0,"",0,0,0,0,
- -1,0,0,"",0,0,0,0,
- -1,0,0,"",0,0,0,0,
- -1,0,0,"",0,0,0,0,
- -1,0,0,"",0,0,0,0,
- -1,0,0,"",0,0,0,0,
- -1,0,0,"",0,0,0,0,
- -1,0,0,"",0,0,0,0,
- -1,0,0,"",0,0,0,0,
- -1,0,0,"",0,0,0,0,
- -1,0,0,"",0,0,0,0,
- -1,0,0,"",0,0,0,0,
- -1,0,0,"",0,0,0,0,
- -1,0,0,"",0,0,0,0};
-
- struct fildef fdef; /* File Definition structure */
-
-
- /********************************************************************
- * KA_OPEN - Open a keyed access file.
- *
- * All Keyed Access files have the extension 'KAF'.
- *
- ********************************************************************/
- ka_open(int fn, char * fname)
- {
- unsigned mode;
- char buffer[256]; /* Used to build filename & read in file defs */
-
- if(strlen(fname)>76) /* Validate filename parameter */
- {
- kaerror = 12; /* Filename too Long */
- return(ERR);
- }
-
- if(fn <0 || fn >= KEYFILES) /* Validate filenumber */
- {
- kaerror = 10; /* Invalid Channel Number */
- return(ERR);
- }
-
- if(ftbl[fn].handle != -1)
- {
- kaerror = 1;
- return(ERR); /* File already Open */
- }
-
- strcpy(buffer, fname); /* Build the KAF filename */
- strcat(buffer, ".KAF");
-
- /*
- * Set the mode for opening or for Creating a new file
- */
- mode = O_RDWR | O_BINARY | O_DENYNONE;
-
- ftbl[fn].handle = open(buffer, mode ,S_IREAD | S_IWRITE);
- if(ftbl[fn].handle==ERR)
- {
- kaerror = 3; /* Unable to Open File */
- return(ERR);
- }
-
- /*
- * Read the File's Definition and set the file table values
- */
- if(read(ftbl[fn].handle, &fdef, sizeof(fdef))==ERR ||
- strcmp(fdef.signature, "KAFSII"))
- {
- kaerror = 2; /* Not a KAFSII file */
- return(ERR);
- }
-
- ftbl[fn].keysize = fdef.keysize; /* size of key */
- ftbl[fn].recsize = fdef.recsize; /* Record size */
- ftbl[fn].records = fdef.records;
- ftbl[fn].kpb = fdef.kpb; /* Keys per Block */
- ftbl[fn].hblocks =fdef.hblocks; /* Number of hash Blocks */
- ftbl[fn].dbeg = fdef.dbeg; /* Start of Data Pointer */
- strcpy(ftbl[fn].fname, fdef.filename);
- return(OK);
- }
-
- /** -------- Close Files -------- */
- void ka_close_all(void)
- {
- int i;
- for(i=0;i<KEYFILES;i++) ka_close(i);
- }
- void ka_close(int fn)
- {
- if(ftbl[fn].handle > -1) close(ftbl[fn].handle);
- ftbl[fn].handle = -1;
- }
-
- /** -----------------------------------------------------------------
- ** READ_KEY - Read a key access file by key.
- ** This function hashes the key to find the record if Rec = SOF
- ** If Rec != SOF reads for key at rec + 1
- ** ----------------------------------------------------------------- */
- read_key(int fn, char *keyarg, void *buffer)
- {
- long hblk;
- long startblock; /* Starting point for search */
- int brec; /* Record number in Block */
- char *hp;
-
- key[0]=0; /* Blank Key for Return */
- if(ftbl[fn].handle == FCLOSED || fn < 0 || fn >= KEYFILES)
- {
- kaerror = 4; /* File not open */
- return(ERR);
- }
-
- if(rec==SOF)
- {
- hblk = khash(keyarg, ftbl[fn].hblocks); /* Get the Hashed Block */
- rec = hblk * ftbl[fn].kpb; /* Calculate record number at beginning */
- }
- else
- {
- rec++;
- if(rec > ftbl[fn].records) rec = 0; /* Wrap At EOF */
- hblk = (long)rec/ftbl[fn].kpb; /* Or block based on rec */
- }
-
- if(read_hblk(ftbl[fn].handle, hblk)==ERR) return(ERR);
- startblock = hblk; /* Save for wrap-arounds */
- brec = rec - (hblk * ftbl[fn].kpb);
- hp = hbuf + (brec * ftbl[fn].keysize); /* point to Record in Buffer */
- while(TRUE)
- {
- if(*hp == 0) return(NOTFOUND);
- if(!strcmp(hp,keyarg))
- {
- strcpy(key,hp); /* copy the key */
- return(read_xrec(fn, buffer)); /* FOUND */
- }
- rec++; /* Bump the record number */
- brec++; /* Bump the block record number */
- hp += ftbl[fn].keysize; /* Move the Pointer to the next key */
- if(brec>=ftbl[fn].kpb)
- {
- hblk++;
- if(hblk >= ftbl[fn].hblocks) hblk=0; /* Wrap around at EOF */
- if(hblk == startblock) return(NOTFOUND); /* Oops We wrapped around */
- if(read_hblk(ftbl[fn].handle, hblk)==ERR) return(ERR); /* Read Nxt Blk */
- hp = hbuf; /* Point to beginning of block */
- brec = 0;
- rec = hblk * ftbl[fn].kpb; /* Calculate Record # */
- }
- }
- }
-
- /** -----------------------------------------------------------------
- ** READ_REC - External Access to Read a key access file by Record Number.
- ** This function reads only the Data portion of a record.
- ** Returns the key for the record in global key.
- **
- ** 2.0 Modified to Add Data Offset
- ** ----------------------------------------------------------------- */
- read_rec(int fn, void *buffer)
- {
- long hblk; /* Hash Block number */
- int brec;
- char *kp;
-
- if(read_xrec(fn, buffer)==ERR) return(ERR); /* Get Data First */
-
- hblk = (long)rec / ftbl[fn].kpb; /* get the hash index block no. */
- if(read_hblk(ftbl[fn].handle, hblk)==ERR) return(ERR);
- brec = rec-(hblk * ftbl[fn].kpb); /* Rec # offset into this block */
- kp = hbuf + (brec * ftbl[fn].keysize); /* point to the record */
- strcpy(key,kp); /* Copy in the Key */
- return(OK);
- }
- /** -----------------------------------------------------------------
- ** READ_XREC - Internal Access to Read a key access file by Record Number.
- ** This function reads only the Data portion of a record.
- ** ----------------------------------------------------------------- */
- read_xrec(int fn, void *buffer)
- {
- long fpos;
-
- if(ftbl[fn].handle == FCLOSED || fn < 0 || fn >= KEYFILES)
- {
- kaerror = 4; /* File not open */
- return(ERR);
- }
-
- if(rec > ftbl[fn].records || rec < 0)
- {
- kaerror = 13; /* Beyond File Limit */
- return(ERR);
- }
- fpos = ((long)rec * ftbl[fn].recsize) + ftbl[fn].dbeg;
- if(lseek(ftbl[fn].handle,fpos,0)==ERR)
- {
- kaerror = 5; /* Seek Error on Data File */
- return(ERR);
- }
-
- if(read(ftbl[fn].handle, buffer,(unsigned)ftbl[fn].recsize)==ERR)
- {
- kaerror = 6; /* Read Error on Data File */
- return(ERR);
- }
- return(OK);
- }
-
- /** -----------------------------------------------------------------
- ** WRITE_KEY - Write a new record to a key access file by key.
- ** This function hashes the key to find the record.
- ** ----------------------------------------------------------------- */
- write_key(int fn, char *keyarg, void *buffer)
- {
- long hblk;
- long startblock; /* Starting point for search */
- int brec; /* Record number in Block */
- char *hp;
-
- if(ftbl[fn].handle == FCLOSED || fn < 0 || fn >= KEYFILES)
- {
- kaerror = 4; /* File not open */
- return(ERR);
- }
-
- if(strlen(keyarg)>ftbl[fn].keysize-1)
- {
- kaerror = 11; /* key too big */
- return(ERR);
- }
-
- hblk = khash(keyarg, ftbl[fn].hblocks); /* Get the Hashed Block */
- if(read_hblk(ftbl[fn].handle, hblk)==ERR) return(ERR);
- hp = hbuf; /* Point to beginning of Buffer */
- rec = hblk * ftbl[fn].kpb; /* Calculate record number */
- startblock = hblk; /* Save for wrap-arounds */
- brec = 0;
- while(1)
- {
- if(*hp < 02) /* Found an Empty Slot, empty (00) or deleted (01) */
- {
- if(write_rec(fn, buffer)==ERR) return(ERR); /* Write the Data */
- strcpy(hp,keyarg); /* Copy in the Key */
- if(write_hblk(ftbl[fn].handle, hblk)==ERR) return(ERR);
- else return(OK);
- }
- rec++; /* Bump the record number */
- brec++; /* Bump the block record number */
- hp += ftbl[fn].keysize; /* Move the Pointer to the next key */
- if(brec>=ftbl[fn].kpb)
- {
- hblk++;
- if(hblk >= ftbl[fn].hblocks) hblk=0; /* Wrap around at EOF */
- if(hblk == startblock) return(FILEFULL); /* Oops We wrapped around */
- if(read_hblk(ftbl[fn].handle, hblk)==ERR) return(ERR); /* Read Nxt Blk */
- hp = hbuf; /* Point to beginning of block */
- brec = 0;
- rec = hblk * ftbl[fn].kpb; /* Calculate Record # */
- }
- }
- }
-
- /** -----------------------------------------------------------------
- ** WRITE_REC - Write a record to a key access file by Record #.
- ** This function only writes the Data Portion of a record
- **
- ** 2.0 Modified to add data beginning offset
- **
- ** ----------------------------------------------------------------- */
- write_rec(int fn, void *buffer)
- {
- int fh;
- long fpos;
-
- if(ftbl[fn].handle == FCLOSED || fn < 0 || fn >= KEYFILES)
- {
- kaerror = 4; /* File not open */
- return(ERR);
- }
-
- if(rec > ftbl[fn].records || rec < 0)
- {
- kaerror = 13; /* Beyond File Limit */
- return(ERR);
- }
-
- fh = ftbl[fn].handle; /* Set file handle */
- fpos = ((long)rec * ftbl[fn].recsize) + ftbl[fn].dbeg;
-
- if(lseek(fh,fpos,0)==ERR)
- {
- kaerror = 5; /* Seek Error */
- return(ERR);
- }
- if(write(fh, buffer,(unsigned)ftbl[fn].recsize)==ERR)
- {
- kaerror = 7; /* Write Error */
- return(ERR);
- }
- return(OK);
- }
- write_upd(int fn, void *buffer)
- {
- return(write_rec(fn, buffer));
- }
-
- /** -----------------------------------------------------------------
- ** RDELETE - Delete a record in a key access file by record number.
- ** The record must have previously been read and rec # obtained
- ** ----------------------------------------------------------------- */
- rdelete(int fn, long delrec)
- {
- long hblk;
- int brec;
- char * hp;
-
- if(ftbl[fn].handle == FCLOSED || fn < 0 || fn >= KEYFILES)
- {
- kaerror = 4; /* File not open */
- return(ERR);
- }
-
- if(rec > ftbl[fn].records || rec < 0)
- {
- kaerror = 13; /* Beyond File Limit */
- return(ERR);
- }
-
- rec = delrec;
- hblk = (long)delrec / ftbl[fn].kpb; /* get the hash index block no. */
- if(read_hblk(ftbl[fn].handle, hblk)==ERR) return(ERR); /* read it */
- brec = rec-(hblk * ftbl[fn].kpb); /* Rec # offset into this block */
- hp = hbuf + (brec * ftbl[fn].keysize); /* point to the record */
- *hp = 01; /* Delete the Record */
- if(write_hblk(ftbl[fn].handle, hblk)==ERR) return(ERR); /* Write it */
- return(OK);
- }
-
- /** -----------------------------------------------------------------
- ** READ_SEQ - Read sequential. Reads next record based on rec.
- ** Esentially reads rec+1 for next available record.
- ** ----------------------------------------------------------------- */
- read_seq(int fn, void *buffer)
- {
- long hblk;
- int brec;
- char *hp;
-
- if(ftbl[fn].handle == FCLOSED || fn < 0 || fn >= KEYFILES)
- {
- kaerror = 4; /* File not open */
- return(ERR);
- }
-
- key[0]=0; /* Null the key */
- while(TRUE)
- {
- if(rec+1 > ftbl[fn].records) return(KAEOF); /* End of file */
- rec++; /* increment record */
- hblk = rec / ftbl[fn].kpb; /* get the hash index block no. */
- if(read_hblk(ftbl[fn].handle, hblk)==ERR) return(ERR);
- brec = rec-(hblk * ftbl[fn].kpb); /* Rec # offset into this block */
- hp = hbuf + (brec * ftbl[fn].keysize); /* point to the record */
- if(*hp > 2)
- {
- strcpy(key, hp); /* Copy the key into the key storage */
- return(read_xrec(fn, buffer)); /* Read the record & return */
- }
- if(*hp == 0) /* NO more recs this block */
- {
- hblk++;
- if(hblk >= ftbl[fn].hblocks) return(KAEOF); /* At EOF */
- rec = (hblk * ftbl[fn].kpb)-1; /* Get beginning rec number -1 */
- }
- }
- }
-
- /** -----------------------------------------------------------------
- ** READ_HBLK - Read Hash Block to Hash Block Buffer
- **
- ** 2.0 Modified to add key offset
- ** ----------------------------------------------------------------- */
- read_hblk(int fh, long blkno)
- {
- kaerror = 8;
- if(lseek(fh, ((long)blkno * HBLOCKSIZE)+KEYSTART, 0)==ERR) return(ERR);
- return(read(fh, hbuf, (unsigned)HBLOCKSIZE));
- }
-
- /** -----------------------------------------------------------------
- ** WRITE_HBLK - Write Hash Block from Hash Block Buffer
- **
- ** 2.0 Modified to add key offset
- ** ----------------------------------------------------------------- */
- write_hblk(int fh, long blkno)
- {
- kaerror = 9;
- if(lseek(fh, ((long)blkno * HBLOCKSIZE)+KEYSTART, 0)==ERR) return(ERR);
- return(write(fh, hbuf, (unsigned)HBLOCKSIZE));
- }
-
- /** ------------------------------------------------------------------
- ** KHASH - Hash a key and return the hash block number
- ** ------------------------------------------------------------------ */
- long khash(char *hkey, long blocks)
- {
- char *hp;
- double hc;
- long val;
-
- hc = (double)blocks-1;
- hp = hkey; /* Point to key for Hashing */
- while (*hp) hc += *hp++ - 32;
- val = (long)fmod(hc, (double)blocks);
- return(val);
- }
-
- /**************************************************************************
- * FILECOMMIT - Commit a file's changes etc to disk. Flush.
- *************************************************************************/
- void filecommit(int fnum)
- {
- union REGS regs;
- int rc, ec;
-
- regs.h.ah = 0x68; /* Call to Flush */
- regs.x.bx = ftbl[fnum].handle; /* Give the file's handle */
-
- intdos(®s, ®s);
- rc = regs.x.cflag;
- if(rc != 0) ec = _doserrno;
-
- }
-
-